#include "winVisualize.hpp"
#include <commdlg.h>

#define SOLVE_BUTTON_ID 1001
#define GENERATE_BUTTON_ID 1003
#define SAVE_BUTTON_ID 1002

// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// 窗口类的定义
WNDCLASS wc;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

    // 解析命令行参数
    ParseCommandLine(lpCmdLine);

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_CROSS);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("MyWindowClass");

    // 注册窗口类
    if (!RegisterClass(&wc))
    {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 创建窗口
    HWND hWnd = CreateWindow(TEXT("MyWindowClass"), TEXT("Sokoban"),
                             WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 启用窗口的拖放功能
    DragAcceptFiles(hWnd, TRUE);

    // 显示窗口并更新
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// 窗口过程函数实现
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    wchar_t ch;

    int click_x;
    int click_y;
    switch (message)
    {
    case WM_CREATE:
        if (path.size() > 0)
            mainp.openFile(path);
        else
        {
            _State s = mapGen.GenerateMap();
            mainp = MainProcess(s);
        }
        havebeensolved = false;
        // 创建按钮
        CreateWindowEx(0, TEXT("Button"), TEXT("Solve"),
                       WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                       MARGIN * 0, 0, MARGIN * 2, MARGIN,
                       hWnd, (HMENU)SOLVE_BUTTON_ID, GetModuleHandle(NULL), NULL);
        CreateWindowEx(0, TEXT("Button"), TEXT("Save"),
                       WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                       MARGIN * 4, 0, MARGIN * 2, MARGIN,
                       hWnd, (HMENU)SAVE_BUTTON_ID, GetModuleHandle(NULL), NULL);
        CreateWindowEx(0, TEXT("Button"), TEXT("Generate"),
                       WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                       MARGIN * 2, 0, MARGIN * 2, MARGIN,
                       hWnd, (HMENU)GENERATE_BUTTON_ID, GetModuleHandle(NULL), NULL);

        break;
    case WM_DESTROY:

        PostQuitMessage(0);
        break;

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        draw(hWnd);
        EndPaint(hWnd, &ps);
        break;

    case WM_COMMAND:
        SetFocus(hWnd); // 手动让按钮失去焦点，防用它占有键盘事件
        if (LOWORD(wParam) == SOLVE_BUTTON_ID)
        {
            AutoSolve(hWnd);
        }
        if (LOWORD(wParam) == GENERATE_BUTTON_ID)
        {
            _State s = mapGen.GenerateMap();
            mainp = MainProcess(s);
            havebeensolved = false;
            draw(hWnd);
        }
        if (LOWORD(wParam) == SAVE_BUTTON_ID)
        {
            // 定义一个OPENFILENAME结构体，用于保存文件对话框的设置和结果
            OPENFILENAME ofn;
            TCHAR szFile[MAX_PATH] = TEXT("0.map\0");

            ZeroMemory(&ofn, sizeof(ofn));
            ofn.lStructSize = sizeof(ofn);
            ofn.hwndOwner = hWnd;
            ofn.lpstrFile = szFile;
            ofn.nMaxFile = sizeof(szFile);
            ofn.lpstrFilter = TEXT("MAP Files (*.map)\0*.map\0All Files\0*.*\0\0"); // 文件类型过滤器
            ofn.nFilterIndex = 1;                                                   // 初始显示的过滤器索引
            ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;                    // 确保路径存在且提示是否覆盖现有文件

            // // 显示保存文件对话框
            if (GetSaveFileName(&ofn))
            {
                path=tcharArrayToString(szFile);
                mainp.writeFile(path);
                cout<<"File have been saved."<<endl;
            }
        }
        break;

    case WM_KEYDOWN:
        ch = (wchar_t)wParam;
        if (ch == 'r' || ch == 'R')
            mainp.openFile(path);
        else if (ch == 'q' || ch == 'Q')
            PostQuitMessage(0);
        else
            keyInput(ch);
        draw(hWnd);
        break;

    case WM_LBUTTONDOWN:
        click_x = GET_X_LPARAM(lParam);
        click_y = GET_Y_LPARAM(lParam);
        mouseClick(hWnd, click_x, click_y, false);
        break;

    case WM_RBUTTONDOWN:
        click_x = GET_X_LPARAM(lParam);
        click_y = GET_Y_LPARAM(lParam);
        mouseClick(hWnd, click_x, click_y, true);
        break;

    case WM_DROPFILES:
    {
        HDROP hDrop = (HDROP)wParam;
        UINT fileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // 获取文件数量

        for (UINT i = 0; i < fileCount; i++)
        {
            TCHAR filePath[MAX_PATH];
            DragQueryFile(hDrop, i, filePath, sizeof(filePath)); // 获取每个文件的路径
            path = tcharArrayToString(filePath);
            mainp.openFile(path);
            draw(hWnd);
            break;
        }
        cout << "path:" << path << endl;
        havebeensolved = false;
        DragFinish(hDrop);
        break;
    }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}